home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 6 / CU Amiga Magazine's Super CD-ROM 06 (1996)(EMAP Images)(GB)(Track 1 of 4)[!][issue 1997-01].iso / cucd / prog / gnu-c / src / gcc-2.7.0-amiga / cp / repo.c < prev    next >
C/C++ Source or Header  |  1995-06-15  |  8KB  |  410 lines

  1. /* Code to maintain a C++ template repository.
  2.    Copyright (C) 1995 Free Software Foundation, Inc.
  3.    Contributed by Jason Merrill (jason@cygnus.com)
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 59 Temple Place - Suite 330,
  20. Boston, MA 02111-1307, USA.  */
  21.  
  22. /* My strategy here is as follows:
  23.  
  24.    Everything should be emitted in a translation unit where it is used.
  25.    The results of the automatic process should be easily reproducible with
  26.    explicit code.  */
  27.  
  28. #include <stdio.h>
  29. #include "config.h"
  30. #include "tree.h"
  31. #include "cp-tree.h"
  32. #include "input.h"
  33. #include "obstack.h"
  34.  
  35. extern char * rindex ();
  36. extern char * getenv ();
  37. extern char * getpwd ();
  38.  
  39. static tree pending_repo;
  40. static tree original_repo;
  41. static char *repo_name;
  42. static FILE *repo_file;
  43.  
  44. extern int flag_use_repository;
  45. extern int errorcount, sorrycount;
  46. extern struct obstack temporary_obstack;
  47. extern struct obstack permanent_obstack;
  48.  
  49. #define IDENTIFIER_REPO_USED(NODE)   (TREE_LANG_FLAG_3 (NODE))
  50. #define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE))
  51.  
  52. /* Record the flags used to compile this translation unit.  */
  53.  
  54. void
  55. repo_compile_flags (argc, argv)
  56.      int argc;
  57.      char **argv;
  58. {
  59. }
  60.  
  61. /* If this template has not been seen before, add a note to the repository
  62.    saying where the declaration was.  This may be used to find the
  63.    definition at link time.  */
  64.  
  65. void
  66. repo_template_declared (t)
  67.      tree t;
  68. {}
  69.  
  70. /* Note where the definition of a template lives so that instantiations can
  71.    be generated later.  */
  72.  
  73. void
  74. repo_template_defined (t)
  75.      tree t;
  76. {}
  77.  
  78. /* Note where the definition of a class lives to that template
  79.    instantiations can use it.  */
  80.  
  81. void
  82. repo_class_defined (t)
  83.      tree t;
  84. {}
  85.  
  86. tree
  87. repo_get_id (t)
  88.      tree t;
  89. {
  90.   if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
  91.     {
  92.       t = TYPE_BINFO_VTABLE (t);
  93.       if (t == NULL_TREE)
  94.     return t;
  95.     }
  96.   return DECL_ASSEMBLER_NAME (t);
  97. }
  98.  
  99. /* Note that a template has been used.  If we can see the definition, offer
  100.    to emit it. */
  101.  
  102. void
  103. repo_template_used (t)
  104.      tree t;
  105. {
  106.   tree id;
  107.  
  108.   if (! flag_use_repository)
  109.     return;
  110.  
  111.   id = repo_get_id (t);
  112.   if (id == NULL_TREE)
  113.     return;
  114.   
  115.   if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
  116.     {
  117.       if (IDENTIFIER_REPO_CHOSEN (id))
  118.     mark_class_instantiated (t, 0);
  119.     }
  120.   else if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
  121.     {
  122.       if (IDENTIFIER_REPO_CHOSEN (id))
  123.     mark_function_instantiated (t, 0);
  124.     }
  125.   else
  126.     my_friendly_abort (1);
  127.  
  128.   if (! IDENTIFIER_REPO_USED (id))
  129.     {
  130.       IDENTIFIER_REPO_USED (id) = 1;
  131.       pending_repo = perm_tree_cons (NULL_TREE, id, pending_repo);
  132.     }
  133. }
  134.  
  135. /* Note that the vtable for a class has been used, and offer to emit it.  */
  136.  
  137. void
  138. repo_vtable_used (t)
  139.      tree t;
  140. {
  141.   if (! flag_use_repository)
  142.     return;
  143.  
  144.   pending_repo = perm_tree_cons (NULL_TREE, t, pending_repo);
  145. }
  146.  
  147. /* Note that an inline with external linkage has been used, and offer to
  148.    emit it.  */
  149.  
  150. void
  151. repo_inline_used (fn)
  152.      tree fn;
  153. {
  154.   if (! flag_use_repository)
  155.     return;
  156.  
  157.   /* Member functions of polymorphic classes go with their vtables.  */
  158.   if (DECL_FUNCTION_MEMBER_P (fn) && TYPE_VIRTUAL_P (DECL_CLASS_CONTEXT (fn)))
  159.     {
  160.       repo_vtable_used (DECL_CLASS_CONTEXT (fn));
  161.       return;
  162.     }
  163.  
  164.   pending_repo = perm_tree_cons (NULL_TREE, fn, pending_repo);
  165. }
  166.  
  167. /* Note that a particular typeinfo node has been used, and offer to
  168.    emit it.  */
  169.  
  170. void
  171. repo_tinfo_used (ti)
  172.      tree ti;
  173. {
  174. }
  175.  
  176. void
  177. repo_template_instantiated (t, extern_p)
  178.      tree t;
  179.      int extern_p;
  180. {
  181.   if (! extern_p)
  182.     {
  183.       tree id = repo_get_id (t);
  184.       if (id)
  185.     IDENTIFIER_REPO_CHOSEN (id) = 1;
  186.     }
  187. }
  188.  
  189. static char *
  190. save_string (s, len)
  191.      char *s;
  192.      int len;
  193. {
  194.   return obstack_copy0 (&temporary_obstack, s, len);
  195. }
  196.  
  197. static char *
  198. get_base_filename (filename)
  199.      char *filename;
  200. {
  201.   char *p = getenv ("COLLECT_GCC_OPTIONS");
  202.   char *output = 0;
  203.   int compiling = 0;
  204.  
  205.   if (p)
  206.     while (*p)
  207.       {
  208.     char *q = p;
  209.     while (*q && *q != ' ') q++;
  210.     if (*p == '-' && p[1] == 'o')
  211.       {
  212.         p += 2;
  213.         if (p == q)
  214.           {
  215.         p++; q++;
  216.         if (*q)
  217.           while (*q && *q != ' ') q++;
  218.           }
  219.  
  220.         output = save_string (p, q - p);
  221.       }
  222.     else if (*p == '-' && p[1] == 'c')
  223.       compiling = 1;
  224.     if (*q) q++;
  225.     p = q;
  226.       }
  227.  
  228.   if (compiling && output)
  229.     return output;
  230.  
  231.   if (p && ! compiling)
  232.     {
  233.       warning ("-frepo must be used with -c");
  234.       flag_use_repository = 0;
  235.       return NULL;
  236.     }
  237.  
  238.   p = rindex (filename, '/');
  239.   if (p)
  240.     return p+1;
  241.   else
  242.     return filename;
  243. }        
  244.  
  245. static void
  246. open_repo_file (filename)
  247.      char *filename;
  248. {
  249.   register char *p, *q;
  250.   char *s = get_base_filename (filename);
  251.  
  252.   if (s == NULL)
  253.     return;
  254.  
  255.   p = rindex (s, '/');
  256.   if (! p)
  257.     p = s;
  258.   p = rindex (p, '.');
  259.   if (! p)
  260.     p = s + strlen (s);
  261.  
  262.   obstack_grow (&permanent_obstack, s, p - s);
  263.   repo_name = obstack_copy0 (&permanent_obstack, ".rpo", 4);
  264.  
  265.   repo_file = fopen (repo_name, "r");
  266. }
  267.  
  268. static char *
  269. afgets (stream)
  270.      FILE *stream;
  271. {
  272.   int c;
  273.   while ((c = getc (stream)) != EOF && c != '\n')
  274.     obstack_1grow (&temporary_obstack, c);
  275.   if (obstack_object_size (&temporary_obstack) == 0)
  276.     return NULL;
  277.   obstack_1grow (&temporary_obstack, '\0');
  278.   return obstack_finish (&temporary_obstack);
  279. }
  280.  
  281. void
  282. init_repo (filename)
  283.      char *filename;
  284. {
  285.   char *buf;
  286.  
  287.   if (! flag_use_repository)
  288.     return;
  289.  
  290.   open_repo_file (filename);
  291.  
  292.   if (repo_file == 0)
  293.     return;
  294.  
  295.   while (buf = afgets (repo_file))
  296.     {
  297.       switch (buf[0])
  298.     {
  299.     case 'A':
  300.     case 'D':
  301.     case 'M':
  302.       break;
  303.     case 'C':
  304.     case 'O':
  305.       {
  306.         tree id = get_identifier (buf + 2);
  307.         tree orig;
  308.  
  309.         if (buf[0] == 'C')
  310.           {
  311.         IDENTIFIER_REPO_CHOSEN (id) = 1;
  312.         orig = integer_one_node;
  313.           }
  314.         else
  315.           orig = NULL_TREE;
  316.  
  317.         original_repo = perm_tree_cons (orig, id, original_repo);
  318.       }
  319.       break;
  320.     default:
  321.       error ("mysterious repository information in %s", repo_name);
  322.     }
  323.       obstack_free (&temporary_obstack, buf);
  324.     }
  325. }
  326.  
  327. static void
  328. reopen_repo_file_for_write ()
  329. {
  330.   if (repo_file)
  331.     fclose (repo_file);
  332.   repo_file = fopen (repo_name, "w");
  333.  
  334.   if (repo_file == 0)
  335.     {
  336.       error ("can't create repository information file `%s'", repo_name);
  337.       flag_use_repository = 0;
  338.     }
  339. }
  340.  
  341. /* Emit any pending repos.  */
  342.  
  343. void
  344. finish_repo ()
  345. {
  346.   tree t;
  347.   char *p;
  348.   int repo_changed = 0;
  349.  
  350.   if (! flag_use_repository)
  351.     return;
  352.  
  353.   /* Do we have to write out a new info file?  */
  354.  
  355.   /* Are there any old templates that aren't used any longer or that are
  356.      newly chosen?  */
  357.   
  358.   for (t = original_repo; t; t = TREE_CHAIN (t))
  359.     {
  360.       if (! IDENTIFIER_REPO_USED (TREE_VALUE (t))
  361.       || (! TREE_PURPOSE (t) && IDENTIFIER_REPO_CHOSEN (TREE_VALUE (t))))
  362.     {
  363.       repo_changed = 1;
  364.       break;
  365.     }
  366.       IDENTIFIER_REPO_USED (TREE_VALUE (t)) = 0;
  367.     }
  368.  
  369.   /* Are there any templates that are newly used?  */
  370.   
  371.   if (! repo_changed)
  372.     for (t = pending_repo; t; t = TREE_CHAIN (t))
  373.       {
  374.     if (IDENTIFIER_REPO_USED (TREE_VALUE (t)))
  375.       {
  376.         repo_changed = 1;
  377.         break;
  378.       }
  379.       }
  380.  
  381.   if (! repo_changed || errorcount || sorrycount)
  382.     goto out;
  383.  
  384.   reopen_repo_file_for_write ();
  385.  
  386.   if (repo_file == 0)
  387.     goto out;
  388.  
  389.   fprintf (repo_file, "M %s\n", main_input_filename);
  390.  
  391.   p = getpwd ();
  392.   fprintf (repo_file, "D %s\n", p);
  393.  
  394.   p = getenv ("COLLECT_GCC_OPTIONS");
  395.   if (p != 0)
  396.     fprintf (repo_file, "A %s\n", p);
  397.  
  398.   for (t = pending_repo; t; t = TREE_CHAIN (t))
  399.     {
  400.       tree val = TREE_VALUE (t);
  401.       char type = IDENTIFIER_REPO_CHOSEN (val) ? 'C' : 'O';
  402.  
  403.       fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (val));
  404.     }
  405.  
  406.  out:
  407.   if (repo_file)
  408.     fclose (repo_file);
  409. }
  410.